package com.syh.jn.scm.service.impl.supplier.stock;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtAssert;
import com.alibaba.dubbo.config.annotation.Service;
import com.syh.core.ddd.event.annotation.DomainEventHandle;
import com.syh.core.ddd.infrastructure.repository.AggregateRepository;
import com.syh.core.ddd.service.AbstractServiceImpl;
import com.syh.jn.scm.domain.operation.entity.supplier.OperaSupplier;
import com.syh.jn.scm.domain.operation.event.supplier.OperaSupplierEvent;
import com.syh.jn.scm.domain.supplier.entity.stock.StockLoss;
import com.syh.jn.scm.domain.supplier.entity.stock.StockLossItem;
import com.syh.jn.scm.domain.supplier.event.StockLossEvent;
import com.syh.jn.scm.domain.supplier.repository.stock.StockLossRepository;
import com.syh.jn.scm.dto.supplier.stock.StockLossItemVo;
import com.syh.jn.scm.dto.supplier.stock.StockLossMto;
import com.syh.jn.scm.dto.supplier.stock.StockLossSto;
import com.syh.jn.scm.dto.supplier.stock.StockLossVo;
import com.syh.jn.scm.service.api.supplier.stock.StockLossService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * 报损单管理
 */
@Service
@Transactional
public class StockLossServiceImpl extends AbstractServiceImpl<StockLossSto, StockLossMto, StockLossVo, StockLoss, Long> implements StockLossService {
  @Autowired
  private StockLossRepository stockLossRepository;

  @Override
  protected AggregateRepository<StockLoss, Long> getAggregateRepository() {
    return stockLossRepository;
  }

  /**
   * 保存报损单和报损单项
   *
   * @param sto
   * @return
   */
  @Override
  public Long save(StockLossSto sto) {
    StockLoss stockLoss = new StockLoss(sto);
    return stockLossRepository.add(stockLoss);
  }

  /**
   * 修改报损单和报损单项
   *
   * @param mto
   */
  @Override
  public void update(StockLossMto mto) {
    StockLoss loss = this.getStockLossById(mto.getId());
    loss.modify(mto);
    stockLossRepository.update(loss);
  }

  /**
   * 删除报损单和报损单项
   *
   * @param id
   */
  @Override
  public void delete(Long id) {
    StockLoss loss = this.getStockLossById(id);
    loss.destroy();
    stockLossRepository.remove(loss);
  }

  @Override
  public StockLossVo getById(Long id) {
    StockLossVo stockLossVo = stockLossRepository.getKeyView(id);
    stockLossVo.setItems(stockLossRepository.getItemVosById(id));
    return stockLossVo;
  }

  /**
   * 根据id获取报损聚合体
   *
   * @param id
   * @return
   */
  @Override
  public StockLossVo getVo(Long id) {
    //获取报损项聚合体
    StockLoss stockLoss = stockLossRepository.getById(id);
    ExtAssert.notNull(stockLoss, "对象为空");

    //业务模型转Vo
    StockLossVo vo = new StockLossVo();
    List<StockLossItemVo> itemVoList = new ArrayList<>();
    ExtBeanUtils.copyProperties(stockLoss, vo);
    stockLoss.getLossItems().stream().forEach(item -> {
      StockLossItemVo stockLossItemVo = new StockLossItemVo();
      ExtBeanUtils.copyProperties(item, stockLossItemVo);

      itemVoList.add(stockLossItemVo);
    });

    vo.setItems(itemVoList);
    return vo;
  }

  /**
   * 获取明细对象
   *
   * @param id      明细id
   * @param goodsId 明细中商品id
   * @return
   */
  @Override
  public StockLossItemVo getItemByIdAndGoodsId(Long id, Long goodsId) {
    return this.entityTransVo(stockLossRepository.getItemByIdAndGoodsId(id, goodsId));
  }

  /**
   * 取消订单
   *
   * @param id
   * @return
   */
  @Override
  public void cancel(Long id) {
    StockLoss loss = this.getStockLossById(id);
    loss.cancel();
    stockLossRepository.updateStatus(loss);
  }

  /**
   * 解锁
   *
   * @param id
   */
  @Override
  public void unLock(Long id) {
    StockLoss loss = this.getStockLossById(id);
    loss.unLock();
    stockLossRepository.updateStatus(loss);
  }

  /**
   * 确认报损单
   *
   * @param id
   */
  @Override
  public void enabled(Long id) {
    StockLoss loss = this.getStockLossById(id);
    loss.enabled();
    stockLossRepository.updateStatus(loss);
    //发送事件
    Object[] obj = new Object[]{loss};
    this.publicEvent(StockLossEvent.buildStockLossConfirmStatus(obj));
  }

  /**
   * 未确认报损单
   *
   * @param id
   */
  @Override
  public void disabled(Long id) {
    StockLoss loss = this.getStockLossById(id);
    loss.disabled();
    stockLossRepository.updateStatus(loss);
    //发送事件
    Object[] obj = new Object[]{loss};
    this.publicEvent(StockLossEvent.buildStockLossUnStatus(obj));
  }

  /**
   * 消费者：监听服务商反开账（删除所有该服务商的报损单）
   */
  @DomainEventHandle(OperaSupplierEvent.SUPPLIER_REVERSAL_ACCOUNT)
  protected void handleSupplierReversalAccount(OperaSupplier supplier) {
    this.stockLossRepository.deleteByBusinessEntityId(supplier.getId());
  }

  /**
   * 根据id获取报损单并且判空
   *
   * @param id
   * @return
   */
  private StockLoss getStockLossById(Long id) {
    ExtAssert.notNull(id, "id为空");
    StockLoss loss = stockLossRepository.getById(id);
    ExtAssert.notNull(loss, "对象为空");
    return loss;
  }

  /**
   * 领域对象转vo
   *
   * @param entity
   * @return
   */
  private StockLossItemVo entityTransVo(StockLossItem entity) {
    StockLossItemVo vo = new StockLossItemVo();
    ExtBeanUtils.copyProperties(entity, vo);
    return vo;
  }
}
